#ifndef __ALLOTTO_H
#define __ALLOTTO_H
#include "stdtype.h"
#include "memslot.h"
#include "dlist.h"
#include "mmblock.h"
#include "mutex.h"

/**
 * calculate the minimum size of memory that will allocate from slot
 * @param osize: the object size
 * @param n: number of object
 */
#define mx_allotto_msize_calc(osize, n) (sizeof(mx_allotto_pool_t) + osize * n)

/**
 * memory pool of object-allotter structure definition
 */
typedef struct
{
    struct
    {
        mx_dlist_t dlist;       // for `freebase` or `fullbase`
        mx_memslot_pt slot;     // associated memory slot
        mx_mmblock_t mmblock;
    } header;
    mx_uint8_t payload[];
} mx_allotto_pool_t, *mx_allotto_pool_pt;

/**
 * object-allotter structure definition
 */
typedef struct
{
    /* memory slot affinity */
    struct
    {
        __MX_MEMSLOT_AFFI_ATTRS;
    } affi;

    mx_mutex_t mutex;           // for object allocate or free
    mx_usize_t msize;           // minimum size of pool (sizeof(mx_allotto_pool_t) + osize * N)
    mx_usize_t osize;           // object size
    mx_usize_t used;            // the size of used memory
    mx_dlist_pt freebase;       // free chain of pools
    mx_dlist_pt fullbase;       // full chain of pools
} mx_allotto_t, *mx_allotto_pt;

/* initialize the descriptor of object-allotter */
void mx_allotto_init (mx_allotto_pt poatr);
/* allocate an object */
mx_void_pt mx_allotto_alloc (mx_allotto_pt poatr);
/* free the memory of object */
void mx_allotto_free (mx_allotto_pt poatr, mx_void_pt addr);
/* get the size of used memory in object-allotter */
mx_usize_t mx_allotto_getused (mx_allotto_pt poatr);

#endif
